package com.zitangkou.user.filter;

import com.google.gson.Gson;
import com.zitangkou.common.enums.RespEnum;
import com.zitangkou.common.global.ConstantValue;
import com.zitangkou.common.global.GlobalException;
import com.zitangkou.common.global.UserContent;
import com.zitangkou.user.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 验证 token 过滤器
 *
 * @author Deng Ningning
 * @version 1.0
 * @date 2020/9/2 17:25
 */
@Slf4j
@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {

    private final Gson gson;

    private final JwtUtil jwtUtil;

    private final UserDetailsService userDetailsService;

    @Autowired
    public TokenAuthenticationFilter(Gson gson, JwtUtil jwtUtil, UserDetailsService userDetailsService) {
        this.gson = gson;
        this.jwtUtil = jwtUtil;
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String token = request.getHeader(ConstantValue.TOKEN_HEADER);
        // token 为空，没有权限
        if (!StringUtils.isEmpty(token)) {
            // 验证 token
            String userInfo = jwtUtil.validateToken(token);
            UserContent user;
            try {
                user = gson.fromJson(userInfo, UserContent.class);
            } catch (Exception e) {
                throw new GlobalException(RespEnum.TOKEN_IS_NULL);
            }
            if (null == user) {
                throw new GlobalException(RespEnum.TOKEN_IS_NULL);
            }
            UserDetails userDetails = userDetailsService.loadUserByUsername(user.getEnterpriseId() + "#" + user.getUserAccount());
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(userDetails, token, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authentication);
            // 将用户信息放入请求中供拦截器获取设置上下文参数
            request.setAttribute(ConstantValue.USER_ID, user.getUserId());
            request.setAttribute(ConstantValue.ENTERPRISE_ID, user.getEnterpriseId());
        }
        String enterpriseId = request.getHeader(ConstantValue.ENTERPRISE_ID_HEADER);
        // 判断数值型字符串且不为空
        if (request.getAttribute(ConstantValue.ENTERPRISE_ID) == null && NumberUtils.isDigits(enterpriseId)) {
            request.setAttribute(ConstantValue.ENTERPRISE_ID, enterpriseId);
        }
        filterChain.doFilter(request, response);
    }
}
